home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BCI NET
/
BCI NET Dec 94.iso
/
archives
/
applications
/
wp
/
ags-261-030.lha
/
gs261gdevretina.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-15
|
14KB
|
538 lines
/*
* NAME
* gdevretina.c
*
* DESCRIPTION
* GhostScript device-driver for the Macro-Systems
* RETINA graphics board. Currently this driver does not work
* with 16-Bit Color-Lookup-Tables
*
* LEGAL STATUS
* GNUware
*
* AUTHOR
* Andreas Heitmann
*
* EMAIL
* andreas@gotcha.swb.de
* ah@hrz.uni-kassel.de
* ah@rbg.informatik.th-darmstadt.de
*
*/
#include <stdio.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <graphics/gfx.h>
#include <retina/retina.h>
#include <retina/clib/retina_protos.h>
#include "gs.h"
#include "gxdevice.h"
#include "gdevretina.h"
#include "gsmatrix.h"
#include <stdlib.h>
#define X_DPI 72
#define Y_DPI 72
#define RETINA_LIB_VERSION 3
#if RETINA_LIB_VERSION<4
#define FILLRECTHACK
#endif
#define COPYMONOHACK
#ifdef COPYMONOHACK
#define RETINA_COPY_MONO r_copy_mono
#else
#define RETINA_COPY_MONO r_fast_copy_mono
#endif
void TEST(char *x)
{
char test[3];
eprintf(x);
eprintf("\n");
fflush(stderr);
fgets(test,2,stdin);
}
/* forward declarations */
dev_proc_open_device(r_open_device);
dev_proc_close_device(r_close_device);
dev_proc_map_rgb_color(r_map_rgb_color_8_16);
dev_proc_map_color_rgb(r_map_color_rgb_8_16);
dev_proc_map_rgb_color(r_map_rgb_color_24);
dev_proc_map_color_rgb(r_map_color_rgb_24);
dev_proc_fill_rectangle(r_fill_rectangle);
dev_proc_copy_mono(RETINA_COPY_MONO);
dev_proc_copy_color(r_copy_color);
dev_proc_draw_line(r_draw_line);
dev_proc_get_initial_matrix(r_get_initial_matrix);
#define retina_procs_24 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_24, r_map_color_rgb_24, r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
#define retina_procs_16 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_8_16, r_map_color_rgb_8_16, r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
#define retina_procs_8 { r_open_device, r_get_initial_matrix, gx_default_sync_output, gx_default_output_page, r_close_device, r_map_rgb_color_8_16, r_map_color_rgb_8_16 , r_fill_rectangle, gx_default_tile_rectangle, RETINA_COPY_MONO, r_copy_color, r_draw_line, gx_default_get_bits, gx_default_get_props, gx_default_put_props }
private gx_device_procs gs_retina_procs_8 = retina_procs_8;
private gx_device_procs gs_retina_procs_16 = retina_procs_16;
private gx_device_procs gs_retina_procs_24 = retina_procs_24;
#define gs_retina_skel(procs,name,colors,mode) {sizeof(retina_device),&procs,name,0,0,XPPI,YPPI,no_margins,colors,FALSE,NULL,mode,0,NULL,NULL,NULL}
retina_device gs_retina8_device = gs_retina_skel(gs_retina_procs_8, "retina8" ,dci_color( 8, 31, 4),MID_DEFAULT_08);
retina_device gs_retina16_device = gs_retina_skel(gs_retina_procs_16,"retina16",dci_color(16,255,256),MID_DEFAULT_16);
retina_device gs_retina24_device = gs_retina_skel(gs_retina_procs_24,"retina24",dci_color(24,255,256),MID_DEFAULT_24);
/** procedures **/
/* tests if the pixel coordinates have valid values */
static boolean
retina_is_valid_area(gx_device * dev, int x, int y, int width, int height)
{
return x >= 0 && y >= 0 && x + width <= rdev->width && y + height <= rdev->height;
}
/* Amiga library bases */
struct RetinaBase *RetinaBase = NULL;
struct GfxBase *GfxBase = NULL;
void
gs_retina_setrgb(gx_device *dev,byte r,byte g,byte b)
{
rdev->palette[rdev->ncols][0]=r;
rdev->palette[rdev->ncols][1]=g;
rdev->palette[rdev->ncols][2]=b;
rdev->ncols++;
}
/*
* preallocate colors for video-modes with color-lookup tables
*/
int
preallocate_colors(gx_device *dev)
{
int res=0;
switch (rdev->screenmode) {
case MID_DEFAULT_08:
case MID_DEFAULT_16:
rdev->palette =(byte (*)[3])calloc(1 << dev->color_info.depth, 3*sizeof(byte));
if (NULL != rdev->palette) {
gx_color_index color;
byte r, g, b;
/* reset index counter */
rdev->ncols = 0;
/* allocate black & white as first 2 colors */
gs_retina_setrgb(dev,0, 0, 0);
gs_retina_setrgb(dev,255, 255, 255);
/* allocate evenly space color cube */
while (rdev->ncols < RGB_COLS) {
color = rdev->ncols - 1;
r = ((color & RED_MASK) >> (GREEN_BITS + BLUE_BITS))
* ((1 << dev->color_info.depth) - 1) / (RED_COLS - 1);
g = ((color&GREEN_MASK) >> BLUE_BITS)
* ((1 << dev->color_info.depth) - 1) / (GREEN_COLS - 1);
b = (color&BLUE_MASK)
* ((1 << dev->color_info.depth) - 1) / (RED_COLS - 1);
/* Retina_SetPalette(rdev->rs,rdev->ncols,r,g,b); */
gs_retina_setrgb(dev,r,g,b);
}
/* load the color map */
Retina_LoadPalette(rdev->rs, 0, rdev->ncols, (UBYTE *) rdev->palette);
}
else {
eprintf("gs retina: no memory for colormap\n");
res = -1;
}
break;
default:
}
return res;
}
int
open_screen(gx_device *dev)
{
int res=0;
if(NULL!=(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))) {
if(NULL!=(RetinaBase=(struct RetinaBase *)OpenLibrary
("retina.library",RETINA_LIB_VERSION))) {
if (NULL !=(rdev->rs = Retina_OpenScreen(
rdev->width == 0 ? RSCR_MAXWIDTH : rdev->width,
rdev->height == 0 ? RSCR_MAXHEIGHT : rdev->height,
rdev->screenmode,
RSFF_AUTOADJUST | RSFF_DONTCLEARONOPEN | RSFF_DONTCLEARONCLOSE,
NULL))) {
Retina_ClearScreen(rdev->rs);
/*
* real screensize may have changed due to memory lack, so correct the
* variables
*/
rdev->width = rdev->rs->_rs_Width;
rdev->height = rdev->rs->_rs_Height;
}
else {
eprintf("gs retina: can't open retina screen.\n");
res = -1;
}
}
else {
res = -1;
eprintf1("gs retina: can't open version %d of the retina.library.\n",
RETINA_LIB_VERSION);
}
}
else {
res = -1;
eprintf("gs retina: can't open graphics library.\n");
}
return res;
}
void
setup_rdev(gx_device *dev)
{
rdev->wz_scale_x = (float)rdev->width / PRE_WIDTH;
rdev->wz_scale_y = (float)rdev->height / PRE_HEIGHT;
rdev->is_open = TRUE;
}
int
r_open_device(gx_device *dev)
{
int res=0;
char buf[3];
rdev->is_open=FALSE;
rdev->rs=NULL;
if(0==(res=open_screen(dev))) {
preallocate_colors(dev);
setup_rdev(dev);
}
return res;
}
/*
* closes retina device
* - close screen
* - close library
*/
int
r_close_device(gx_device * dev)
{
/*
* free color palette, if allocated
*/
switch (rdev->screenmode) {
case MID_DEFAULT_08:
case MID_DEFAULT_16:
if (rdev->palette != NULL) free(rdev->palette);
break;
case MID_DEFAULT_24:
break;
}
/*
* close screen, if opened
*/
if (rdev->rs != NULL) {
Retina_CloseScreen(rdev->rs);
rdev->is_open = FALSE;
}
/*
* close libraries
*/
if (RetinaBase != NULL) CloseLibrary((struct Library *)RetinaBase);
if (GfxBase != NULL) CloseLibrary((struct Library *)GfxBase);
/*
* exit without error
*/
return 0;
}
/*
* modified sun mapping routines
*/
gx_color_index
r_map_rgb_color_24(gx_device * dev, gx_color_value r, gx_color_value g, gx_color_value b)
{
return
(gx_color_value_to_byte(r)<<16)+
(gx_color_value_to_byte(g)<<8)+
gx_color_value_to_byte(b);
}
gx_color_index
r_map_rgb_color_8_16(gx_device * dev, gx_color_value r, gx_color_value g, gx_color_value b)
{
gx_color_index ret = gx_no_color_index;
byte red_val, green_val, blue_val;
gx_color_index i;
static int warn = 1;
/*
* Determine the RGB values at display resolution we ideally would want
* this color to be mapped into.
*/
red_val =gx_color_value_to_byte(r);
green_val=gx_color_value_to_byte(g);
blue_val =gx_color_value_to_byte(b);
/*
* Look for an exact match among the colors already allocated. This
* includes the pre-allocated default color cube.
*/
for (i = 0; i < rdev->ncols; i++) {
if (rdev->palette[i][0] == red_val &&
rdev->palette[i][1] == green_val &&
rdev->palette[i][2] == blue_val) {
ret = i;
}
}
if (ret == gx_no_color_index) {
if (rdev->ncols == (1 << dev->color_info.depth)) {
if (warn) {
eprintf("gs retina: last spare color map entry allocated\n");
warn = 0;
}
}
else {
Retina_SetPalette(rdev->rs, i, red_val, green_val, blue_val);
gs_retina_setrgb(dev,red_val, green_val, blue_val);
ret = i;
} /* else alloc new color */
} /* end if no spare colors */
return ret;
}
/*
* map retina color index to ghostscript rgb-value
*/
int
r_map_color_rgb_24(gx_device * dev, gx_color_index color, ushort prgb[3])
{
prgb[0]=gx_color_value_from_byte((color>>16)&0xff);
prgb[1]=gx_color_value_from_byte((color>> 8)&0xff);
prgb[2]=gx_color_value_from_byte( color &0xff);
return 0;
}
int
r_map_color_rgb_8_16(gx_device * dev, gx_color_index color, ushort prgb[3])
{
prgb[0]=gx_color_value_from_byte(rdev->palette[color][0]);
prgb[1]=gx_color_value_from_byte(rdev->palette[color][1]);
prgb[2]=gx_color_value_from_byte(rdev->palette[color][2]);
return 0;
}
/*
* fill rectangle with color
*/
int
r_fill_rectangle(gx_device * dev, int x, int y, \
int width, int height, gx_color_index color)
{
int res = 0;
if (retina_is_valid_area(dev, x, y, width, height)) {
#ifdef FILLRECTHACK
switch (rdev->screenmode) {
case MID_DEFAULT_24:
#endif
Retina_SetDrMd(rdev->rs, RDM_JAM1);
Retina_SetAPen(rdev->rs, color);
Retina_RectFill(rdev->rs, x, y, x + width, y + height);
#ifdef FILLRECTHACK
break;
/*
* There is a bug in the RectFill routine of retina.library version 2.3
* in the 8 & 16 Bit color-mode so i can't use it.
*
* This bug has been fixed in Version 3.8 of retina.library
*/
case MID_DEFAULT_08:
case MID_DEFAULT_16:
{
int xx;
Retina_SetDrMd(rdev->rs, RDM_JAM1);
Retina_SetAPen(rdev->rs, color);
for (xx = x + width - 1; xx >= x; xx--)
Retina_Line(rdev->rs, xx, y, xx, y + height - 1);
break;
}
}
#endif
}
else res = -1;
return res;
}
/*
* draw line
*/
int
r_draw_line(gx_device * dev, int x0, int y0, int x1, int y1, \
gx_color_index color)
{
int h;
if (!(y1 == y0 && x1 == x0)) {
Retina_SetDrMd(rdev->rs, RDM_JAM1);
Retina_SetAPen(rdev->rs, color);
Retina_Line(rdev->rs, x0, y0, x1, y1);
}
return 0;
}
#ifdef COPYMONOHACK
int r_copy_mono
(gx_device *dev,\
const unsigned char *data, int data_x, int raster, gx_bitmap_id id,\
int x, int y, int width, int height,\
gx_color_index color0, gx_color_index color1)
{
boolean draw = TRUE;
int res = 0;
unsigned char *dp; /* pointer to first byte of each line */
static gx_bitmap_id old_id = gx_no_bitmap_id;
unsigned char bit; /* bitmask */
long byte; /* byte number in scanline */
gx_color_index color; /* actual color: color_c */
long ix, iy; /* coordinates in data space */
int c; /* color index: 0..1 */
/*
* this is a hack and has to be replaced in future versions of gdevretina.c
*
* i am trying to replace this by a bitmap-copy but not before the
* next release of the retina-software
*/
if (retina_is_valid_area(dev, x, y, width, height)) {
for (c = 0; c <= 1; c++) {
color = (c == 0) ? color0 : color1;
if (color != gx_no_color_index) {
dp = data;
for (iy = 0; iy < height; iy++) {
for (byte = 0, ix = 0; ix < width; byte++) {
for (bit = 1 << 7; bit && ix < width; ix++, bit >>= 1) {
if (dp[byte] & bit)
Retina_SetPixel(rdev->rs, x + ix, y + iy, color);
}
}
dp += raster;
}
}
}
}
else res = -1;
return res;
}
#endif
/*
* The following function is a replacement for the slow r_copy_mono routine.
* It still doesn't work because Retina_WriteBitMap doesn't support
* writing WBMMODE_STD BitMaps to 24Bit Screens.
* If the bug is fixed in newer versions of the retina.library i will
* undefine COPYMONOHACK :)
*/
#ifndef COPYMONOHACK
int
r_fast_copy_mono(gx_device * dev, unsigned char *data, int data_x, \
int raster, gx_bitmap_id id, int x, int y, \
int width, int height, gx_color_index color0, \
gx_color_index color1)
{
unsigned char pal[2 * 3];
static struct BitMap mybm;
int res = 0;
if (retina_is_valid_area(dev, x, y, width, height)) {
InitBitMap(&mybm, 1, width, height);
#ifdef DEBUG
printf("bm.bbr=%d\n", mybm.BytesPerRow);
printf("bm.row=%d\n", mybm.Rows);
printf("bm.flg=%d\n", mybm.Flags);
printf("bm.dpt=%d\n", mybm.Depth);
printf("x=%d y=%d w=%d h=%d raster=%d\n", x, y, width, height, raster);
#endif
/*
* correct the number of bytes per row, because gfx has it's own way to
* compute the number of bytes from the number of pixels in each line.
*/
mybm.BytesPerRow = raster;
mybm.Planes[0] = (PLANEPTR) data;
#ifdef DEBUG
{
int i, j;
for (j = 0; j < height; j++) {
for (i = 0; i < raster; i++) {
printf("%02x ", *(mybm.Planes[0] + i + j * raster));
}
puts("");
}
}
#endif
pal[0] = ((unsigned char *)&color0)[1];
pal[1] = ((unsigned char *)&color0)[2];
pal[2] = ((unsigned char *)&color0)[3];
pal[3] = ((unsigned char *)&color1)[1];
pal[4] = ((unsigned char *)&color1)[2];
pal[5] = ((unsigned char *)&color1)[3];
Retina_WriteBitMap(rdev->rs, &mybm, pal, x, y, width, WBMMODE_STD);
}
else
res = -1;
return res;
}
#endif
int
r_copy_color(
gx_device *dev,\
const unsigned char *data, int data_x, int raster, gx_bitmap_id id,\
int x, int y, int width, int height)
{
int res = 0;
if (retina_is_valid_area(dev, x, y, width, height)) {
switch (rdev->screenmode) {
case MID_DEFAULT_24:
Retina_WriteRect(data, 0, 0, raster, RECTMODE_RGB, rdev->rs, x, y, width,
height, NULL);
break;
case MID_DEFAULT_08:
Retina_WriteRect(data, 0, 0, raster, RECTMODE_256, rdev->rs, x, y, width,
height, NULL);
break;
}
}
else
res = -1;
return res;
}
void
r_get_initial_matrix(gx_device * dev, gs_matrix * m)
{
/* scale the user coordinates with SCALE */
m->xy = m->yx = m->tx = 0;
m->xx = rdev->x_pixels_per_inch * SCALE * rdev->wz_scale_x /X_DPI;
m->yy = -rdev->y_pixels_per_inch * SCALE * rdev->wz_scale_y/Y_DPI;
m->ty = rdev->height;
}